//模式特点：定义一个用于创建对象的接口，让子类决定实例化哪一个类。这使得一个类的实例化延迟到其子类。
//程序实例：1. 简单工厂改造。
package main

import (
	"fmt"
)

type RealOperation struct {
	numberA float64
	numberB float64
}

func (p *RealOperation) SetNumA(numA float64) {
	p.numberA = numA
}

func (p *RealOperation) SetNumB(numB float64) {
	p.numberB = numB
}

type OperateAdd struct {
	RealOperation
}

func (p *OperateAdd) GetResult() float64 {
	return p.numberA + p.numberB
}

type OperateSub struct {
	RealOperation
}

func (p *OperateSub) GetResult() float64 {
	return p.numberA - p.numberB
}

type OperateMul struct {
	RealOperation
}

func (p *OperateMul) GetResult() float64 {
	return p.numberA * p.numberB
}

type OperateDiv struct {
	RealOperation
}

func (p *OperateDiv) GetResult() float64 {

	if p.numberB == 0 {
		panic("被除数不能为0")
	}
	return p.numberA / p.numberB
}

type Operation interface {
	GetResult() float64
	SetNumA(float64)
	SetNumB(float64)
}

type Ifactory interface {
	createOperation() Operation
}

type AddFactory struct {
}

func (a *AddFactory) createOperation() (operation Operation) {
	operation = new(OperateAdd)
	return
}

type SubFactory struct {
}

func (s *SubFactory) createOperation() (operation Operation) {
	operation = new(OperateSub)
	return
}

type DivFactory struct {
}

func (d *DivFactory) createOperation() (operation Operation) {
	operation = new(OperateDiv)
	return
}

type MulFactory struct {
}

func (m *MulFactory) createOperation() (operation Operation) {
	operation = new(OperateMul)
	return
}

func main() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()
	ifac := new(DivFactory)
	oper := ifac.createOperation()
	oper.SetNumA(1.0)
	oper.SetNumB(3.0)
	fmt.Println(oper.GetResult())
}
